library(cluster)
library(mclust)
library(lattice)
library(tidyverse)
library(maptree)
library(mice)
library(magrittr)
library(mclust)
library(mice)
library(nFactors)
library(poLCA)
library(Rtsne)
library(corrplot)

1 Utility Functions

utility_histogramplotter <- function(x) {
  lattice::histogram( ~ x)
}
seg.summ <- function(data, groups) {
  aggregate(data, list(groups), function(x) mean(as.numeric(as.character(x))))
}
minmax <- function(x)
{
    return((x- min(x)) /(max(x)-min(x)))
}
plot_bi_plots <- function(df, y,...) {
  old.par = par()
  par(mar=c(5,4,5,2))
  on.exit(expr = 'par = old.par')
  prcomp(df) %>% biplot(col = c('gray', 'red'), cex = .8, main = y, ...)
}
adjust_q13 <- function(df){
  df %<>% 
    mutate(q13_visitfreq_social= (q13r1+q13r2+q13r3 +q13r11)/4,
           q13_visitfreq_music = (q13r4+q13r7+q13r8 +q13r9)/4,
           q13_visitfreq_video = (q13r5+q13r6+q13r10+q13r12)/4)
  df[,!str_detect(names(df),'q13r')]
}
adjust_q24 <- function(df){
  df %<>% 
    mutate(
      q24_tech_posatt = (q24r1+q24r2+q24r3+q24r5+q24r6)/5,
      q24_tech_enter = (q24r7+q24r8)/2,
      q24_tech_comm = (q24r10+q24r11+q24r12)/3,
      q24_tech_negatv = (q24r4+q24r9)/2
    )
  df[,!str_detect(names(df),'q24r')]
}
adjust_q25 <- function(df){
  df %<>% 
    mutate(
      q25_prsnlty_leader = (q25r1+q25r2+q25r3+q25r4)/4,
      q25_prsnlty_risk   = (q25r5+q25r7+q25r8)/3,
      q25_prsnlty_drive  = (q25r9+q25r10+q25r11+q25r12)/4,
      q25_prsnlty_follower = q25r6
    )
  df[,!str_detect(names(df),'q25r')]
}
adjust_q26 <- function(df){
  df %<>% 
    mutate(
      q26_shopsavvy_bargain =  (q26r3+q26r5)/2,
      q26_shopsavvy_brands = (q26r18+q26r7+q26r13+q26r14+q26r15)/5,
      q26_shopsavvy_earn2spend = (q26r13+q26r16+q26r4)/3,
      q26_shopsavvy_applover = (q26r17+q26r12+q26r10+q26r8+q26r6+q26r9)/6,
      q26_shopsavvy_children = q26r11,
    )
  df[,!str_detect(names(df),'q26r')]
}
adjust_q2 <- function(df){
  df %<>%
    mutate(
      q2_apple = ifelse(q2r1==1|q2r2==1,1,0),
      q2_andriod = q2r3,
      q2_windows = q2r6,
      q2_tablet = q2r8,
      q2_other = ifelse(q2r4==1|q2r5==1|q2r7==1|q2r9==1,1,0)
    )
  df[,!str_detect(names(df),'q2r')]
}
adjust_q4 <- function(df){
    df %<>%
    mutate(
      q4_use_music_apps =q4r1,
      q4_use_tv_apps =ifelse(q4r2==1|q4r3==1|q4r4==1,1,0),
      q4_use_game_apps =q4r5,
      q4_use_social_apps =q4r6,
      q4_use_news_apps =ifelse(q4r7==1|q4r9==1,1,0),
      q4_use_shop_apps =q4r8,
      q4_use_none_apps =q4r11
    )
  df[,!str_detect(names(df),'q4r')]
}
adjust_race <- function(df){
  df %>% 
    mutate(
      q54_white  = ifelse(q54==1,1,0),
      q54_black  = ifelse(q54==2,1,0),
      q54_asian  = ifelse(q54==3,1,0),
      q54_hawai  = ifelse(q54==4,1,0),
      q54_native =  ifelse(q54==5,1,0),
      q54_other  = ifelse(q54==6,1,0),
      q55_latino =  ifelse(q55==1,1,0)
    ) %>% 
    dplyr::select(-q54,-q55)
}
adjust_gender <- function(df){
  df %>% 
    mutate(q57 = ifelse(q57==1,1,0))
}
adjust_marital <- function(df){
  df %>% 
    mutate(q49 = ifelse(q49==1,1,0))
}
adjust_q11 <- function(df){
  #Q11 has artificial ordinality between #of apps increasing, and response==5 as "Dont know"
  #This function resolves this problem
  df %>% 
    mutate(q11 = ifelse(q11==5 | q11==6, 0, q11))
}
adjust_children <- function(df){
  df %>% 
    dplyr::select(-q50r2_inftod,-q50r3_6_12,-q50r4_13_17,-q50r5_adult)
}
adjust_income <- function(df){
  df %>% 
    dplyr::mutate(q56 = case_when(
      q56 <= 4 ~ 1,
      q56 >= 5 & q56 <=8 ~ 2,
      q56 >= 9 & q56 <=11 ~ 3,
      q56 >= 12 & q56 <= 13 ~ 4,
      q56 >= 14 ~ 5
    ))
}
adjust_age <- function(df){
  df %>% 
    dplyr::mutate(
      q1 = case_when(
        q1 <= 2 ~ 1,
        q1 >= 3 & q1 <= 5 ~ 2,
        q1 >= 6 & q1 <= 8 ~ 3,
        q1 >= 9 & q1 <= 11 ~ 4,
        q1 >= 12 ~ 5,
      )
    )
}
adjust_names <- function(df){
  df %>% 
    dplyr::rename(
      q1_age=q1,
      q11_appnum = q11,
      q12_freeapppc = q12,
      q48_edu = q48,
      q49_marital = q49,
      q56_income = q56,
      q57_mf = q57,
      q50r1_nochild = q50r1,
      q50r2_inftod = q50r2, 
      q50r3_6_12 = q50r3,
      q50r4_13_17 = q50r4,
      q50r5_adult = q50r5
    )
}

2 Data Prep

load('../data/apphappyData.RData')
df_labs <- tbl_df(apphappy.3.labs.frame)
df_nums <- tbl_df(apphappy.3.num.frame)
rm(apphappy.3.num.frame); rm(apphappy.3.labs.frame)
df_labs$q57 <- as.factor(df_labs$q57)
df_labs$caseID <- NULL
df_nums$caseID <- NULL
df_labs$q2r10 <- NULL
df_nums$q2r10 <- NULL
df_labs$q5r1 <- NULL
df_nums$q5r1 <- NULL

3 Remove missing values

3.1 Handle the case of the missing apps?

df_nums$q12[is.na(df_nums$q12)] <- 0
df_nums %>% xtabs(~q12+q11,.,addNA = T)
   q11
q12   1   2   3   4   5   6
  0   0   0   0   0   0  24
  1   6   9   5   3   1   0
  2  31  56  48  66   2   0
  3  23  42 117 114  11   0
  4  12  44 150 198  12   0
  5  23  44 158 209  20   0
  6  68  78 131  71  24   0
df_nums %>% xtabs(~q4r10+q11,.,addNA = T)
     q11
q4r10   1   2   3   4   5   6
    0 156 254 564 595  67  24
    1   7  19  45  66   3   0
df_nums %>% xtabs(~q4r11+q11,.,addNA = T)
     q11
q4r11   1   2   3   4   5   6
    0 148 267 606 661  65   8
    1  15   6   3   0   5  16
# RULE (A): IF q4r11=TRUE, it means you have no apps. So that means q11 has to equal 6, i.e. NONE. Data shows this is violated. Correcting using this rule.
df_nums$q11[df_nums$q4r11==TRUE] <- 6
df_nums %>% xtabs(~q4r11+q11,.,addNA = T)
     q11
q4r11   1   2   3   4   5   6
    0 148 267 606 661  65   8
    1   0   0   0   0   0  45

3.2 Small changes

Since q11 can be ordinal, “none” should equal 0 instead of 6 to preserve ordinality

# RULE (B): Set q11=6 to q11=0
df_nums$q11[df_nums$q11==6] <- 0
df_nums %>% xtabs(~q11,., addNA = T)
q11
  0   1   2   3   4   5 
 53 148 267 606 661  65 

‘Dont know’ doesn’t add value. Perhaps these can be set to NA and then imputed using mice.

# RULE (C): Set q11 Dont know to NA
df_nums$q11[df_nums$q11==0] <- NA
df_nums %>% xtabs(~q11,., addNA = T)
q11
   1    2    3    4    5 <NA> 
 148  267  606  661   65   53 
# RULE (D): All NA values for q12 set to 6, since I'm approximating that if you don't have any apps, might as well could as free?
df_nums$q12[is.na(df_nums$q12)] <- 6
df_nums %>% xtabs(~q12,., addNA = T)
q12
  0   1   2   3   4   5   6 
 24  24 203 307 416 454 372 
map_int(df_nums,~sum(is.na(.x))) %>% sort() %>% tail(3) %>% barchart(main='Missing values')

3.3 Imputing using mice

map_df(df_nums,~as.factor(.x)) %>% 
  mice::mice(printFlag = T, m = 5, method = 'rf') -> miceFit

 iter imp variable
  1   1  q11  q57
  1   2  q11  q57
  1   3  q11  q57
  1   4  q11  q57
  1   5  q11  q57
  2   1  q11  q57
  2   2  q11  q57
  2   3  q11  q57
  2   4  q11  q57
  2   5  q11  q57
  3   1  q11  q57
  3   2  q11  q57
  3   3  q11  q57
  3   4  q11  q57
  3   5  q11  q57
  4   1  q11  q57
  4   2  q11  q57
  4   3  q11  q57
  4   4  q11  q57
  4   5  q11  q57
  5   1  q11  q57
  5   2  q11  q57
  5   3  q11  q57
  5   4  q11  q57
  5   5  q11  q57
Number of logged events: 25
df_nums <- tbl_df(mice::complete(miceFit))

4 Bi Plots

# questions_to_consolidate <- c('q13','q24','q25','q26')
# plot_bi_plots(df_nums %>% dplyr::select(contains(questions_to_consolidate[1])),questions_to_consolidate[1])
# plot_bi_plots(df_nums %>% dplyr::select(contains(questions_to_consolidate[2])),questions_to_consolidate[2], xlim=c(0,.05), ylim=c(-0.01,0.002))
# plot_bi_plots(df_nums %>% dplyr::select(contains(questions_to_consolidate[3])),questions_to_consolidate[3])
# plot_bi_plots(df_nums %>% dplyr::select(contains(questions_to_consolidate[4])),questions_to_consolidate[4], xlim=c(0,0.05),ylim=c(-0.011,0.005))

5 Data Prep

5.1 Sub grouping

df_nums <- map_df(df_nums,~as.numeric(as.character(.x)))
df_nums_adj <- df_nums %>%  
  adjust_q13() %>% 
  adjust_q24() %>% 
  adjust_q25() %>% 
  adjust_q26() %>% 
  adjust_q2() %>% 
  adjust_q4() %>% 
  adjust_race() %>% 
  adjust_gender() %>% 
  adjust_marital() %>% 
  adjust_income() %>%
  adjust_age() %>% 
  adjust_q11() %>% 
  adjust_names() %>% 
  adjust_children()
glimpse(df_nums_adj)
Observations: 1,800
Variables: 43
$ q1_age                   <dbl> 1, 1, 3, 1, 2, 1, 2, 2, 2, 2, 2, 1, 1, 3, 1, 3, 2, 2, 1, 2, 1, 2, 4, 3, 2, 1, 1, 2, 2, 1, 2, 3, 2, 3, 1, 1, 2, 1, 1, 2, 2, 1, 2, 3, 2, 4, ...
$ q11_appnum               <dbl> 4, 3, 3, 4, 3, 4, 4, 3, 1, 2, 3, 2, 4, 4, 4, 3, 4, 3, 4, 4, 2, 4, 1, 4, 4, 1, 3, 3, 3, 4, 3, 4, 3, 1, 2, 3, 2, 4, 4, 0, 4, 3, 4, 3, 4, 4, ...
$ q12_freeapppc            <dbl> 5, 5, 6, 4, 6, 3, 3, 6, 5, 2, 5, 6, 2, 3, 5, 4, 2, 2, 3, 5, 3, 6, 2, 5, 4, 3, 4, 0, 4, 4, 3, 4, 5, 6, 6, 2, 6, 3, 5, 5, 3, 4, 2, 6, 4, 2, ...
$ q48_edu                  <dbl> 3, 4, 3, 4, 4, 1, 3, 4, 3, 3, 4, 3, 4, 3, 4, 3, 2, 4, 6, 6, 1, 5, 3, 4, 6, 1, 3, 2, 2, 3, 3, 3, 3, 4, 3, 2, 3, 3, 4, 2, 4, 3, 6, 4, 3, 4, ...
$ q49_marital              <dbl> 0, 0, 1, 0, 1, 0, 0, 0, 1, 1, 1, 0, 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0, 0, 1, 1, 0, 1, ...
$ q50r1_nochild            <dbl> 1, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 1, 1, 0, 1, 0, 0, 0, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 1, 0, 1, 1, 1, 1, 0, 0, 1, 1, 1, 0, 1, 0, ...
$ q56_income               <dbl> 2, 3, 4, 2, 2, 1, 1, 3, 2, 2, 2, 2, 4, 3, 2, 4, 3, 2, 2, 2, 2, 4, 3, 3, 5, 1, 2, 2, 1, 2, 3, 3, 2, 3, 1, 2, 3, 1, 1, 2, 2, 2, 3, 1, 4, 5, ...
$ q57_mf                   <dbl> 1, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, ...
$ q13_visitfreq_social     <dbl> 2.50, 3.00, 3.25, 4.00, 2.50, 4.00, 2.50, 2.25, 2.75, 2.00, 2.75, 3.25, 1.25, 3.25, 2.00, 2.25, 2.75, 2.00, 2.75, 3.25, 3.25, 3.25, 4.00, ...
$ q13_visitfreq_music      <dbl> 3.75, 3.50, 2.75, 3.25, 3.50, 3.50, 4.00, 2.50, 2.00, 1.25, 3.50, 3.25, 1.75, 3.25, 2.50, 3.75, 2.50, 2.75, 4.00, 3.25, 2.50, 2.50, 2.75, ...
$ q13_visitfreq_video      <dbl> 2.50, 2.00, 2.50, 2.50, 1.75, 2.25, 3.25, 3.25, 2.00, 1.25, 3.50, 2.00, 1.50, 3.25, 2.25, 3.00, 1.75, 2.00, 3.25, 1.75, 3.25, 2.00, 3.25, ...
$ q24_tech_posatt          <dbl> 2.8, 2.8, 3.0, 3.0, 2.2, 3.4, 2.8, 2.0, 2.6, 2.8, 2.2, 2.0, 1.4, 2.6, 2.8, 2.2, 1.0, 3.6, 1.0, 2.6, 1.0, 3.2, 4.4, 2.6, 2.0, 2.2, 1.0, 2.4...
$ q24_tech_enter           <dbl> 2.0, 2.0, 1.5, 3.0, 2.5, 1.0, 2.5, 2.0, 3.0, 2.5, 2.5, 1.0, 1.5, 2.0, 1.5, 1.5, 1.0, 1.5, 2.5, 2.5, 1.0, 1.0, 4.5, 2.0, 2.5, 3.0, 1.0, 4.5...
$ q24_tech_comm            <dbl> 2.666667, 1.333333, 2.666667, 3.666667, 3.333333, 1.000000, 3.000000, 2.333333, 3.000000, 2.333333, 4.333333, 1.000000, 2.000000, 1.666667...
$ q24_tech_negatv          <dbl> 1.0, 3.0, 4.5, 3.0, 1.5, 4.5, 1.5, 4.0, 4.5, 3.0, 5.5, 6.0, 2.0, 5.0, 3.5, 5.0, 1.0, 2.0, 4.0, 3.5, 1.0, 4.0, 4.0, 3.5, 2.0, 3.0, 1.0, 2.5...
$ q25_prsnlty_leader       <dbl> 1.50, 2.75, 2.50, 2.00, 3.25, 3.00, 3.00, 3.25, 2.75, 2.00, 2.00, 1.00, 1.25, 2.25, 1.50, 2.25, 1.25, 2.50, 1.75, 2.50, 2.75, 1.50, 4.75, ...
$ q25_prsnlty_risk         <dbl> 1.666667, 2.333333, 3.333333, 2.666667, 3.666667, 3.000000, 1.666667, 3.000000, 3.000000, 2.333333, 2.666667, 1.333333, 1.333333, 3.000000...
$ q25_prsnlty_drive        <dbl> 2.75, 2.25, 2.00, 3.25, 3.00, 2.50, 2.50, 2.25, 2.75, 2.25, 3.00, 1.00, 1.75, 3.00, 1.50, 3.00, 2.25, 2.50, 1.50, 1.00, 2.25, 2.50, 2.00, ...
$ q25_prsnlty_follower     <dbl> 5, 5, 6, 5, 4, 4, 2, 5, 5, 2, 6, 5, 2, 6, 5, 6, 3, 1, 4, 5, 3, 5, 6, 6, 2, 5, 1, 5, 5, 3, 4, 6, 4, 6, 6, 2, 5, 3, 4, 5, 5, 5, 6, 6, 6, 5, ...
$ q26_shopsavvy_bargain    <dbl> 2.5, 3.5, 3.0, 3.0, 3.0, 3.0, 3.5, 1.5, 3.5, 1.5, 2.5, 2.0, 1.5, 3.5, 3.5, 2.5, 1.0, 3.0, 3.5, 2.0, 3.5, 1.5, 3.5, 3.5, 2.5, 3.5, 1.0, 3.5...
$ q26_shopsavvy_brands     <dbl> 3.4, 3.2, 3.4, 3.0, 4.0, 3.2, 2.8, 3.8, 5.4, 1.4, 4.4, 3.6, 2.0, 3.6, 2.8, 4.6, 1.4, 2.0, 2.0, 3.0, 3.6, 4.6, 4.0, 4.4, 2.0, 4.6, 1.0, 5.8...
$ q26_shopsavvy_earn2spend <dbl> 2.666667, 3.333333, 3.666667, 3.666667, 4.000000, 4.000000, 5.000000, 3.000000, 5.333333, 1.000000, 3.666667, 3.666667, 2.333333, 4.333333...
$ q26_shopsavvy_applover   <dbl> 4.166667, 3.000000, 4.166667, 2.166667, 3.666667, 2.166667, 3.000000, 4.000000, 4.833333, 1.666667, 4.166667, 3.000000, 2.000000, 2.666667...
$ q26_shopsavvy_children   <dbl> 6, 6, 4, 6, 3, 5, 5, 6, 5, 1, 6, 6, 1, 3, 6, 2, 1, 3, 1, 4, 5, 6, 3, 5, 2, 5, 1, 6, 5, 5, 3, 4, 2, 3, 6, 2, 6, 6, 3, 4, 5, 3, 5, 3, 6, 5, ...
$ q2_apple                 <dbl> 0, 1, 0, 0, 1, 1, 1, 0, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 0, 0, 1, 0, 1, 1, 0, 1, 0, 1, 0, 1, 1, ...
$ q2_andriod               <dbl> 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, ...
$ q2_windows               <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, ...
$ q2_tablet                <dbl> 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, ...
$ q2_other                 <dbl> 0, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, ...
$ q4_use_music_apps        <dbl> 1, 0, 0, 1, 1, 1, 1, 0, 0, 1, 0, 1, 1, 1, 1, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, ...
$ q4_use_tv_apps           <dbl> 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 1, 1, 1, 0, 0, ...
$ q4_use_game_apps         <dbl> 0, 1, 0, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 0, 1, 0, 1, 1, 1, 1, 0, 1, 0, 1, 0, ...
$ q4_use_social_apps       <dbl> 1, 1, 1, 1, 1, 0, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, ...
$ q4_use_news_apps         <dbl> 0, 0, 1, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0, 1, 1, 0, 0, 0, 1, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 0, 1, ...
$ q4_use_shop_apps         <dbl> 0, 1, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 0, 1, 1, 0, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 1, ...
$ q4_use_none_apps         <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ...
$ q54_white                <dbl> 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, ...
$ q54_black                <dbl> 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, ...
$ q54_asian                <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ...
$ q54_hawai                <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ...
$ q54_native               <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ...
$ q54_other                <dbl> 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ...
$ q55_latino               <dbl> 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ...

5.2 Selection of basis variables

set1 <- c(
  'q1_age',
  # 'q11_appnum',
  # 'q12_freeapppc',
  'q48_edu',
  'q49_marital',
  'q50r1_nochild',
  'q56_income',
  # 'q57_mf',
  # 'q13_visitfreq_social',
  # 'q13_visitfreq_music',
  # 'q13_visitfreq_video',
  'q24_tech_posatt',
  'q24_tech_enter',
  'q24_tech_comm',
  'q24_tech_negatv',
  'q25_prsnlty_leader',
  'q25_prsnlty_risk',
  'q25_prsnlty_drive',
  'q25_prsnlty_follower',
  'q26_shopsavvy_bargain',
  'q26_shopsavvy_brands',
  'q26_shopsavvy_earn2spend',
  'q26_shopsavvy_applover',
  'q26_shopsavvy_children',
  'q2_apple',
  'q2_andriod',
  'q2_windows',
  # 'q2_tablet',
  # 'q2_other',
  # 'q4_use_music_apps',
  # 'q4_use_tv_apps',
  # 'q4_use_game_apps',
  # 'q4_use_social_apps',
  # 'q4_use_news_apps',
  # 'q4_use_shop_apps',
  # 'q4_use_none_apps',
  'q54_white',
  'q54_black',
  'q54_asian',
  'q54_hawai',
  'q54_native',
  # 'q54_other',
  'q55_latino'
)
df_nums_adj_backup <- df_nums_adj
# df_nums_adj <- df_nums_adj_backup
df_nums_adj <- df_nums_adj %>% dplyr::select(one_of(set1))

6 Scaling

scaling_wanted <- T
minmax_wanted <- F
if (scaling_wanted) {
  df_nums_adjscaled <- scale(df_nums_adj)
  centers <- attributes(df_nums_adjscaled)[[3]]
  spreads <- attributes(df_nums_adjscaled)[[4]]
  df_nums_adjscaled <- tbl_df(df_nums_adjscaled)
}
if(minmax_wanted){
  df_nums_adjscaled <- map_df(df_nums_adj, ~minmax(.x))
}
if(!scaling_wanted & !minmax_wanted){
  df_nums_adjscaled <- df_nums_adj
}
head(df_nums_adjscaled)

7 Correlation Plot

df_nums_adjscaled %>% cor() %>% corrplot(method = 'shade',tl.col = 'black',tl.cex = .9, order = 'hclust', hclust.method = 'ward.D2')

8 Dissimilarity Calculations

# ordered=c(1:4,11,13:28)
# symm_bin=c(6:10,12,29:47)
# df_nums_adjscaled[ordered] <- map_df(df_nums_adjscaled[ordered],~as.ordered(.x))
# df_nums_adjscaled[symm_bin] <- map_df(df_nums_adjscaled[symm_bin],~as.factor(.x))
distMat <- daisy(df_nums_adjscaled)
binary variable(s) 3, 4, 19, 20, 21, 22, 23, 24, 25, 26, 27 treated as interval scaled

9 Simple clustering

9.1 H clust

9.1.1 How cophenetic changes with clustering method?

methods <- c('complete','average','ward.D','ward.D2','median','mcquitty','centroid')
method_vs_cop <- map_dbl(methods,~cor(cophenetic(hclust(d = distMat, method = .x)), distMat))
names(method_vs_cop) <- methods
barchart(sort(method_vs_cop))

k = 4
hclustFit <- hclust(d = distMat, method = 'ward.D2')
plot(hclustFit, labels = F)
rect.hclust(hclustFit, k=k, border="red")

hclust_segments <- cutree(hclustFit, k = k)
table(hclust_segments)
hclust_segments
  1   2   3   4 
680 819 194 107 
clusplot(df_nums_adjscaled, hclust_segments, color=TRUE, shade=TRUE, labels=4, lines=0, main="HClust plot")

seg.summ(df_nums_adj, hclust_segments) -> centroids
centroids
cutFit <- cutree(hclustFit, k)
plot(silhouette(cutFit,distMat))

9.2 K-means

9.2.1 How many clusters to use?

wssplot <- function(numsub, nc=15, seed=222) {
  wss <- (nrow(numsub)-1)*sum(apply(numsub,2,var))
  for (i in 2:nc) {
    set.seed(seed)
    wss[i] <- sum(kmeans(numsub, centers=i, iter.max = 1e4)$withinss)}
  plot(1:nc, wss, type="b", xlab="Number of Clusters",
       ylab="Within groups sum of squares")}
wssplot(df_nums_adjscaled)

9.2.2 Solving the k-means model

# Using number of clusters + random starts
k_kmeans = 5
clusterresults <- kmeans(x = df_nums_adjscaled, centers = k_kmeans)
rsquare <- clusterresults$betweenss/clusterresults$totss
cat('\nWithin SS:',clusterresults$withinss,' Sizes:\n',clusterresults$size,'\nrsq:', rsquare)

Within SS: 8205.951 7421.324 7440.387 7106.791 6732.311  Sizes:
 221 360 332 459 428 
rsq: 0.2401794
clusplot(df_nums_adjscaled, clusterresults$cluster, color=TRUE, shade=TRUE, labels=4, lines=0, main="K-means cluster plot")

seg.summ(df_nums_adj, clusterresults$cluster) -> segsummary_results
segsummary_results

9.3 PAM

pamFits <- tibble(k_pam = 2:10)
pamFits$pamFits <- map(pamFits$k_pam, ~pam(df_nums_adjscaled, k = .x))
pamFits$sil_avg_width <- map_dbl(pamFits$pamFits,~.x$silinfo$avg.width)
pamFits
pamFits %>% 
  xyplot(sil_avg_width~as.factor(k_pam),.,type='b')

plot(pamFits$pamFits[[4]])

seg.summ(df_nums_adj, pamFits$pamFits[[4]]$clustering)

10 Model based

mclustFits <- tibble(mclust_clusters=2:8)
mclustFits$mclustFits <- map(mclustFits$mclust_clusters, ~Mclust(df_nums_adjscaled, G = .x))
fitting ...

  |                                                                                                                                                                            
  |                                                                                                                                                                      |   0%
  |                                                                                                                                                                            
  |===========                                                                                                                                                           |   7%
  |                                                                                                                                                                            
  |======================                                                                                                                                                |  13%
  |                                                                                                                                                                            
  |=================================                                                                                                                                     |  20%
  |                                                                                                                                                                            
  |============================================                                                                                                                          |  27%
  |                                                                                                                                                                            
  |=======================================================                                                                                                               |  33%
  |                                                                                                                                                                            
  |==================================================================                                                                                                    |  40%
  |                                                                                                                                                                            
  |=============================================================================                                                                                         |  47%
  |                                                                                                                                                                            
  |=========================================================================================                                                                             |  53%
  |                                                                                                                                                                            
  |====================================================================================================                                                                  |  60%
  |                                                                                                                                                                            
  |===============================================================================================================                                                       |  67%
  |                                                                                                                                                                            
  |==========================================================================================================================                                            |  73%
  |                                                                                                                                                                            
  |=====================================================================================================================================                                 |  80%
  |                                                                                                                                                                            
  |================================================================================================================================================                      |  87%
  |                                                                                                                                                                            
  |===========================================================================================================================================================           |  93%
  |                                                                                                                                                                            
  |======================================================================================================================================================================| 100%
fitting ...

  |                                                                                                                                                                            
  |                                                                                                                                                                      |   0%
  |                                                                                                                                                                            
  |===========                                                                                                                                                           |   7%
  |                                                                                                                                                                            
  |======================                                                                                                                                                |  13%
  |                                                                                                                                                                            
  |=================================                                                                                                                                     |  20%
  |                                                                                                                                                                            
  |============================================                                                                                                                          |  27%
  |                                                                                                                                                                            
  |=======================================================                                                                                                               |  33%
  |                                                                                                                                                                            
  |==================================================================                                                                                                    |  40%
  |                                                                                                                                                                            
  |=============================================================================                                                                                         |  47%
  |                                                                                                                                                                            
  |=========================================================================================                                                                             |  53%
  |                                                                                                                                                                            
  |====================================================================================================                                                                  |  60%
  |                                                                                                                                                                            
  |===============================================================================================================                                                       |  67%
  |                                                                                                                                                                            
  |==========================================================================================================================                                            |  73%
  |                                                                                                                                                                            
  |=====================================================================================================================================                                 |  80%
  |                                                                                                                                                                            
  |================================================================================================================================================                      |  87%
  |                                                                                                                                                                            
  |===========================================================================================================================================================           |  93%
  |                                                                                                                                                                            
  |======================================================================================================================================================================| 100%
fitting ...

  |                                                                                                                                                                            
  |                                                                                                                                                                      |   0%
  |                                                                                                                                                                            
  |===========                                                                                                                                                           |   7%
  |                                                                                                                                                                            
  |======================                                                                                                                                                |  13%
  |                                                                                                                                                                            
  |=================================                                                                                                                                     |  20%
  |                                                                                                                                                                            
  |============================================                                                                                                                          |  27%
  |                                                                                                                                                                            
  |=======================================================                                                                                                               |  33%
  |                                                                                                                                                                            
  |==================================================================                                                                                                    |  40%
  |                                                                                                                                                                            
  |=============================================================================                                                                                         |  47%
  |                                                                                                                                                                            
  |=========================================================================================                                                                             |  53%
  |                                                                                                                                                                            
  |====================================================================================================                                                                  |  60%
  |                                                                                                                                                                            
  |===============================================================================================================                                                       |  67%
  |                                                                                                                                                                            
  |==========================================================================================================================                                            |  73%
  |                                                                                                                                                                            
  |=====================================================================================================================================                                 |  80%
  |                                                                                                                                                                            
  |================================================================================================================================================                      |  87%
  |                                                                                                                                                                            
  |===========================================================================================================================================================           |  93%
  |                                                                                                                                                                            
  |======================================================================================================================================================================| 100%
fitting ...

  |                                                                                                                                                                            
  |                                                                                                                                                                      |   0%
  |                                                                                                                                                                            
  |===========                                                                                                                                                           |   7%
  |                                                                                                                                                                            
  |======================                                                                                                                                                |  13%
  |                                                                                                                                                                            
  |=================================                                                                                                                                     |  20%
  |                                                                                                                                                                            
  |============================================                                                                                                                          |  27%
  |                                                                                                                                                                            
  |=======================================================                                                                                                               |  33%
  |                                                                                                                                                                            
  |==================================================================                                                                                                    |  40%
  |                                                                                                                                                                            
  |=============================================================================                                                                                         |  47%
  |                                                                                                                                                                            
  |=========================================================================================                                                                             |  53%
  |                                                                                                                                                                            
  |====================================================================================================                                                                  |  60%
  |                                                                                                                                                                            
  |===============================================================================================================                                                       |  67%
  |                                                                                                                                                                            
  |==========================================================================================================================                                            |  73%
  |                                                                                                                                                                            
  |=====================================================================================================================================                                 |  80%
  |                                                                                                                                                                            
  |================================================================================================================================================                      |  87%
  |                                                                                                                                                                            
  |===========================================================================================================================================================           |  93%
  |                                                                                                                                                                            
  |======================================================================================================================================================================| 100%
fitting ...

  |                                                                                                                                                                            
  |                                                                                                                                                                      |   0%
  |                                                                                                                                                                            
  |===========                                                                                                                                                           |   7%
  |                                                                                                                                                                            
  |======================                                                                                                                                                |  13%
  |                                                                                                                                                                            
  |=================================                                                                                                                                     |  20%
  |                                                                                                                                                                            
  |============================================                                                                                                                          |  27%
  |                                                                                                                                                                            
  |=======================================================                                                                                                               |  33%
  |                                                                                                                                                                            
  |==================================================================                                                                                                    |  40%
  |                                                                                                                                                                            
  |=============================================================================                                                                                         |  47%
  |                                                                                                                                                                            
  |=========================================================================================                                                                             |  53%
  |                                                                                                                                                                            
  |====================================================================================================                                                                  |  60%
  |                                                                                                                                                                            
  |===============================================================================================================                                                       |  67%
  |                                                                                                                                                                            
  |==========================================================================================================================                                            |  73%
  |                                                                                                                                                                            
  |=====================================================================================================================================                                 |  80%
  |                                                                                                                                                                            
  |================================================================================================================================================                      |  87%
  |                                                                                                                                                                            
  |===========================================================================================================================================================           |  93%
  |                                                                                                                                                                            
  |======================================================================================================================================================================| 100%
fitting ...

  |                                                                                                                                                                            
  |                                                                                                                                                                      |   0%
  |                                                                                                                                                                            
  |===========                                                                                                                                                           |   7%
  |                                                                                                                                                                            
  |======================                                                                                                                                                |  13%
  |                                                                                                                                                                            
  |=================================                                                                                                                                     |  20%
  |                                                                                                                                                                            
  |============================================                                                                                                                          |  27%
  |                                                                                                                                                                            
  |=======================================================                                                                                                               |  33%
  |                                                                                                                                                                            
  |==================================================================                                                                                                    |  40%
  |                                                                                                                                                                            
  |=============================================================================                                                                                         |  47%
  |                                                                                                                                                                            
  |=========================================================================================                                                                             |  53%
  |                                                                                                                                                                            
  |====================================================================================================                                                                  |  60%
  |                                                                                                                                                                            
  |===============================================================================================================                                                       |  67%
  |                                                                                                                                                                            
  |==========================================================================================================================                                            |  73%
  |                                                                                                                                                                            
  |=====================================================================================================================================                                 |  80%
  |                                                                                                                                                                            
  |================================================================================================================================================                      |  87%
  |                                                                                                                                                                            
  |===========================================================================================================================================================           |  93%
  |                                                                                                                                                                            
  |======================================================================================================================================================================| 100%
fitting ...

  |                                                                                                                                                                            
  |                                                                                                                                                                      |   0%
  |                                                                                                                                                                            
  |===========                                                                                                                                                           |   7%
  |                                                                                                                                                                            
  |======================                                                                                                                                                |  13%
  |                                                                                                                                                                            
  |=================================                                                                                                                                     |  20%
  |                                                                                                                                                                            
  |============================================                                                                                                                          |  27%
  |                                                                                                                                                                            
  |=======================================================                                                                                                               |  33%
  |                                                                                                                                                                            
  |==================================================================                                                                                                    |  40%
  |                                                                                                                                                                            
  |=============================================================================                                                                                         |  47%
  |                                                                                                                                                                            
  |=========================================================================================                                                                             |  53%
  |                                                                                                                                                                            
  |====================================================================================================                                                                  |  60%
  |                                                                                                                                                                            
  |===============================================================================================================                                                       |  67%
  |                                                                                                                                                                            
  |==========================================================================================================================                                            |  73%
  |                                                                                                                                                                            
  |=====================================================================================================================================                                 |  80%
  |                                                                                                                                                                            
  |================================================================================================================================================                      |  87%
  |                                                                                                                                                                            
  |===========================================================================================================================================================           |  93%
  |                                                                                                                                                                            
  |======================================================================================================================================================================| 100%
mclustFits$bic <- map_dbl(mclustFits$mclustFits, ~.x[['bic']])
mclustFits$loglik <- map_dbl(mclustFits$mclustFits, ~.x[['loglik']])
mclustFits
mclustFits %>% 
  xyplot(bic+loglik~as.factor(mclust_clusters),., auto.key = T, type = 'b')

summary(mclustFits[[2,'mclustFits']])
---------------------------------------------------- 
Gaussian finite mixture model fitted by EM algorithm 
---------------------------------------------------- 

Mclust VII (spherical, varying volume) model with 3 components: 

 log.likelihood    n df       BIC       ICL
      -6435.472 1800 86 -13515.56 -13664.75

Clustering table:
  1   2   3 
669 808 323 
mclust_clusters <- mclustFits[[2,'mclustFits']]$classification
clusplot(df_nums_adj, mclust_clusters, color=TRUE, shade=TRUE, labels=4, lines=0, main="M Clust Plot, k = 4")

seg.summ(df_nums_adj, mclust_clusters)
mclust_distMat <- daisy(df_nums_adj)
binary variable(s) 3, 4, 19, 20, 21, 22, 23, 24, 25, 26, 27 treated as interval scaled
plot(silhouette(mclust_clusters,mclust_distMat))

LS0tCnRpdGxlOiAiUiBOb3RlYm9vayIKb3V0cHV0OiAKICBodG1sX25vdGVib29rOiAKICAgIGhpZ2hsaWdodDogZXNwcmVzc28KICAgIG51bWJlcl9zZWN0aW9uczogeWVzCiAgICB0aGVtZTogam91cm5hbAotLS0KCmBgYHtyIGxpYnJhcmllc30KbGlicmFyeShjbHVzdGVyKQpsaWJyYXJ5KG1jbHVzdCkKbGlicmFyeShsYXR0aWNlKQpsaWJyYXJ5KHRpZHl2ZXJzZSkKbGlicmFyeShtYXB0cmVlKQpsaWJyYXJ5KG1pY2UpCmxpYnJhcnkobWFncml0dHIpCmxpYnJhcnkobWNsdXN0KQpsaWJyYXJ5KG1pY2UpCmxpYnJhcnkobkZhY3RvcnMpCmxpYnJhcnkocG9MQ0EpCmxpYnJhcnkoUnRzbmUpCmxpYnJhcnkoY29ycnBsb3QpCmBgYAoKIyBVdGlsaXR5IEZ1bmN0aW9ucwpgYGB7cn0KdXRpbGl0eV9oaXN0b2dyYW1wbG90dGVyIDwtIGZ1bmN0aW9uKHgpIHsKICBsYXR0aWNlOjpoaXN0b2dyYW0oIH4geCkKfQpzZWcuc3VtbSA8LSBmdW5jdGlvbihkYXRhLCBncm91cHMpIHsKICBhZ2dyZWdhdGUoZGF0YSwgbGlzdChncm91cHMpLCBmdW5jdGlvbih4KSBtZWFuKGFzLm51bWVyaWMoYXMuY2hhcmFjdGVyKHgpKSkpCn0KbWlubWF4IDwtIGZ1bmN0aW9uKHgpCnsKICAgIHJldHVybigoeC0gbWluKHgpKSAvKG1heCh4KS1taW4oeCkpKQp9CnBsb3RfYmlfcGxvdHMgPC0gZnVuY3Rpb24oZGYsIHksLi4uKSB7CiAgb2xkLnBhciA9IHBhcigpCiAgcGFyKG1hcj1jKDUsNCw1LDIpKQogIG9uLmV4aXQoZXhwciA9ICdwYXIgPSBvbGQucGFyJykKICBwcmNvbXAoZGYpICU+JSBiaXBsb3QoY29sID0gYygnZ3JheScsICdyZWQnKSwgY2V4ID0gLjgsIG1haW4gPSB5LCAuLi4pCn0KYWRqdXN0X3ExMyA8LSBmdW5jdGlvbihkZil7CiAgZGYgJTw+JSAKICAgIG11dGF0ZShxMTNfdmlzaXRmcmVxX3NvY2lhbD0gKHExM3IxK3ExM3IyK3ExM3IzICtxMTNyMTEpLzQsCiAgICAgICAgICAgcTEzX3Zpc2l0ZnJlcV9tdXNpYyA9IChxMTNyNCtxMTNyNytxMTNyOCArcTEzcjkpLzQsCiAgICAgICAgICAgcTEzX3Zpc2l0ZnJlcV92aWRlbyA9IChxMTNyNStxMTNyNitxMTNyMTArcTEzcjEyKS80KQogIGRmWywhc3RyX2RldGVjdChuYW1lcyhkZiksJ3ExM3InKV0KfQphZGp1c3RfcTI0IDwtIGZ1bmN0aW9uKGRmKXsKICBkZiAlPD4lIAogICAgbXV0YXRlKAogICAgICBxMjRfdGVjaF9wb3NhdHQgPSAocTI0cjErcTI0cjIrcTI0cjMrcTI0cjUrcTI0cjYpLzUsCiAgICAgIHEyNF90ZWNoX2VudGVyID0gKHEyNHI3K3EyNHI4KS8yLAogICAgICBxMjRfdGVjaF9jb21tID0gKHEyNHIxMCtxMjRyMTErcTI0cjEyKS8zLAogICAgICBxMjRfdGVjaF9uZWdhdHYgPSAocTI0cjQrcTI0cjkpLzIKICAgICkKICBkZlssIXN0cl9kZXRlY3QobmFtZXMoZGYpLCdxMjRyJyldCn0KYWRqdXN0X3EyNSA8LSBmdW5jdGlvbihkZil7CiAgZGYgJTw+JSAKICAgIG11dGF0ZSgKICAgICAgcTI1X3Byc25sdHlfbGVhZGVyID0gKHEyNXIxK3EyNXIyK3EyNXIzK3EyNXI0KS80LAogICAgICBxMjVfcHJzbmx0eV9yaXNrICAgPSAocTI1cjUrcTI1cjcrcTI1cjgpLzMsCiAgICAgIHEyNV9wcnNubHR5X2RyaXZlICA9IChxMjVyOStxMjVyMTArcTI1cjExK3EyNXIxMikvNCwKICAgICAgcTI1X3Byc25sdHlfZm9sbG93ZXIgPSBxMjVyNgogICAgKQogIGRmWywhc3RyX2RldGVjdChuYW1lcyhkZiksJ3EyNXInKV0KfQphZGp1c3RfcTI2IDwtIGZ1bmN0aW9uKGRmKXsKICBkZiAlPD4lIAogICAgbXV0YXRlKAogICAgICBxMjZfc2hvcHNhdnZ5X2JhcmdhaW4gPSAgKHEyNnIzK3EyNnI1KS8yLAogICAgICBxMjZfc2hvcHNhdnZ5X2JyYW5kcyA9IChxMjZyMTgrcTI2cjcrcTI2cjEzK3EyNnIxNCtxMjZyMTUpLzUsCiAgICAgIHEyNl9zaG9wc2F2dnlfZWFybjJzcGVuZCA9IChxMjZyMTMrcTI2cjE2K3EyNnI0KS8zLAogICAgICBxMjZfc2hvcHNhdnZ5X2FwcGxvdmVyID0gKHEyNnIxNytxMjZyMTIrcTI2cjEwK3EyNnI4K3EyNnI2K3EyNnI5KS82LAogICAgICBxMjZfc2hvcHNhdnZ5X2NoaWxkcmVuID0gcTI2cjExLAogICAgKQogIGRmWywhc3RyX2RldGVjdChuYW1lcyhkZiksJ3EyNnInKV0KfQphZGp1c3RfcTIgPC0gZnVuY3Rpb24oZGYpewogIGRmICU8PiUKICAgIG11dGF0ZSgKICAgICAgcTJfYXBwbGUgPSBpZmVsc2UocTJyMT09MXxxMnIyPT0xLDEsMCksCiAgICAgIHEyX2FuZHJpb2QgPSBxMnIzLAogICAgICBxMl93aW5kb3dzID0gcTJyNiwKICAgICAgcTJfdGFibGV0ID0gcTJyOCwKICAgICAgcTJfb3RoZXIgPSBpZmVsc2UocTJyND09MXxxMnI1PT0xfHEycjc9PTF8cTJyOT09MSwxLDApCiAgICApCiAgZGZbLCFzdHJfZGV0ZWN0KG5hbWVzKGRmKSwncTJyJyldCn0KYWRqdXN0X3E0IDwtIGZ1bmN0aW9uKGRmKXsKICAgIGRmICU8PiUKICAgIG11dGF0ZSgKICAgICAgcTRfdXNlX211c2ljX2FwcHMgPXE0cjEsCiAgICAgIHE0X3VzZV90dl9hcHBzID1pZmVsc2UocTRyMj09MXxxNHIzPT0xfHE0cjQ9PTEsMSwwKSwKICAgICAgcTRfdXNlX2dhbWVfYXBwcyA9cTRyNSwKICAgICAgcTRfdXNlX3NvY2lhbF9hcHBzID1xNHI2LAogICAgICBxNF91c2VfbmV3c19hcHBzID1pZmVsc2UocTRyNz09MXxxNHI5PT0xLDEsMCksCiAgICAgIHE0X3VzZV9zaG9wX2FwcHMgPXE0cjgsCiAgICAgIHE0X3VzZV9ub25lX2FwcHMgPXE0cjExCiAgICApCiAgZGZbLCFzdHJfZGV0ZWN0KG5hbWVzKGRmKSwncTRyJyldCn0KYWRqdXN0X3JhY2UgPC0gZnVuY3Rpb24oZGYpewogIGRmICU+JSAKICAgIG11dGF0ZSgKICAgICAgcTU0X3doaXRlICA9IGlmZWxzZShxNTQ9PTEsMSwwKSwKICAgICAgcTU0X2JsYWNrICA9IGlmZWxzZShxNTQ9PTIsMSwwKSwKICAgICAgcTU0X2FzaWFuICA9IGlmZWxzZShxNTQ9PTMsMSwwKSwKICAgICAgcTU0X2hhd2FpICA9IGlmZWxzZShxNTQ9PTQsMSwwKSwKICAgICAgcTU0X25hdGl2ZSA9ICBpZmVsc2UocTU0PT01LDEsMCksCiAgICAgIHE1NF9vdGhlciAgPSBpZmVsc2UocTU0PT02LDEsMCksCiAgICAgIHE1NV9sYXRpbm8gPSAgaWZlbHNlKHE1NT09MSwxLDApCiAgICApICU+JSAKICAgIGRwbHlyOjpzZWxlY3QoLXE1NCwtcTU1KQp9CmFkanVzdF9nZW5kZXIgPC0gZnVuY3Rpb24oZGYpewogIGRmICU+JSAKICAgIG11dGF0ZShxNTcgPSBpZmVsc2UocTU3PT0xLDEsMCkpCn0KYWRqdXN0X21hcml0YWwgPC0gZnVuY3Rpb24oZGYpewogIGRmICU+JSAKICAgIG11dGF0ZShxNDkgPSBpZmVsc2UocTQ5PT0xLDEsMCkpCn0KYWRqdXN0X3ExMSA8LSBmdW5jdGlvbihkZil7CiAgI1ExMSBoYXMgYXJ0aWZpY2lhbCBvcmRpbmFsaXR5IGJldHdlZW4gI29mIGFwcHMgaW5jcmVhc2luZywgYW5kIHJlc3BvbnNlPT01IGFzICJEb250IGtub3ciCiAgI1RoaXMgZnVuY3Rpb24gcmVzb2x2ZXMgdGhpcyBwcm9ibGVtCiAgZGYgJT4lIAogICAgbXV0YXRlKHExMSA9IGlmZWxzZShxMTE9PTUgfCBxMTE9PTYsIDAsIHExMSkpCn0KYWRqdXN0X2NoaWxkcmVuIDwtIGZ1bmN0aW9uKGRmKXsKICBkZiAlPiUgCiAgICBkcGx5cjo6c2VsZWN0KC1xNTByMl9pbmZ0b2QsLXE1MHIzXzZfMTIsLXE1MHI0XzEzXzE3LC1xNTByNV9hZHVsdCkKfQphZGp1c3RfaW5jb21lIDwtIGZ1bmN0aW9uKGRmKXsKICBkZiAlPiUgCiAgICBkcGx5cjo6bXV0YXRlKHE1NiA9IGNhc2Vfd2hlbigKICAgICAgcTU2IDw9IDQgfiAxLAogICAgICBxNTYgPj0gNSAmIHE1NiA8PTggfiAyLAogICAgICBxNTYgPj0gOSAmIHE1NiA8PTExIH4gMywKICAgICAgcTU2ID49IDEyICYgcTU2IDw9IDEzIH4gNCwKICAgICAgcTU2ID49IDE0IH4gNQogICAgKSkKfQphZGp1c3RfYWdlIDwtIGZ1bmN0aW9uKGRmKXsKICBkZiAlPiUgCiAgICBkcGx5cjo6bXV0YXRlKAogICAgICBxMSA9IGNhc2Vfd2hlbigKICAgICAgICBxMSA8PSAyIH4gMSwKICAgICAgICBxMSA+PSAzICYgcTEgPD0gNSB+IDIsCiAgICAgICAgcTEgPj0gNiAmIHExIDw9IDggfiAzLAogICAgICAgIHExID49IDkgJiBxMSA8PSAxMSB+IDQsCiAgICAgICAgcTEgPj0gMTIgfiA1LAogICAgICApCiAgICApCn0KYWRqdXN0X25hbWVzIDwtIGZ1bmN0aW9uKGRmKXsKICBkZiAlPiUgCiAgICBkcGx5cjo6cmVuYW1lKAogICAgICBxMV9hZ2U9cTEsCiAgICAgIHExMV9hcHBudW0gPSBxMTEsCiAgICAgIHExMl9mcmVlYXBwcGMgPSBxMTIsCiAgICAgIHE0OF9lZHUgPSBxNDgsCiAgICAgIHE0OV9tYXJpdGFsID0gcTQ5LAogICAgICBxNTZfaW5jb21lID0gcTU2LAogICAgICBxNTdfbWYgPSBxNTcsCiAgICAgIHE1MHIxX25vY2hpbGQgPSBxNTByMSwKICAgICAgcTUwcjJfaW5mdG9kID0gcTUwcjIsIAogICAgICBxNTByM182XzEyID0gcTUwcjMsCiAgICAgIHE1MHI0XzEzXzE3ID0gcTUwcjQsCiAgICAgIHE1MHI1X2FkdWx0ID0gcTUwcjUKICAgICkKfQpgYGAKCgojIERhdGEgUHJlcApgYGB7cn0KbG9hZCgnLi4vZGF0YS9hcHBoYXBweURhdGEuUkRhdGEnKQpkZl9sYWJzIDwtIHRibF9kZihhcHBoYXBweS4zLmxhYnMuZnJhbWUpCmRmX251bXMgPC0gdGJsX2RmKGFwcGhhcHB5LjMubnVtLmZyYW1lKQpybShhcHBoYXBweS4zLm51bS5mcmFtZSk7IHJtKGFwcGhhcHB5LjMubGFicy5mcmFtZSkKZGZfbGFicyRxNTcgPC0gYXMuZmFjdG9yKGRmX2xhYnMkcTU3KQpkZl9sYWJzJGNhc2VJRCA8LSBOVUxMCmRmX251bXMkY2FzZUlEIDwtIE5VTEwKZGZfbGFicyRxMnIxMCA8LSBOVUxMCmRmX251bXMkcTJyMTAgPC0gTlVMTApkZl9sYWJzJHE1cjEgPC0gTlVMTApkZl9udW1zJHE1cjEgPC0gTlVMTApgYGAKCjwhLS0gIyBFREEgLS0+Cgo8IS0tICMjIFN1bW1hcmllcyAtLT4KCjwhLS0gYGBge3J9IC0tPgo8IS0tIGdsaW1wc2UoZGZfbGFicykgLS0+CjwhLS0gc2tpbXI6OnNraW0oZGZfbGFicykgLS0+CjwhLS0gYGBgIC0tPgoKPCEtLSAjIyBBZ2UgLS0+Cgo8IS0tIGBgYHtyfSAtLT4KPCEtLSBoaXN0b2dyYW0ofnExLCBkZl9sYWJzKSAtLT4KPCEtLSBgYGAgLS0+Cgo8IS0tICMjIEhvdyBtYW55IGFwcHM/IC0tPgoKPCEtLSBgYGB7cn0gLS0+CjwhLS0gZGZfbGFicyAlPiUgZHBseXI6OnNlbGVjdChjb250YWlucygncTExJykpICU+JSBsYXR0aWNlOjpoaXN0b2dyYW0ofnExMSwuKSAtLT4KPCEtLSBgYGAgLS0+Cgo8IS0tICMjIFBDIGZyZWU/IC0tPgoKPCEtLSBgYGB7cn0gLS0+CjwhLS0gZGZfbGFicyAlPiUgZHBseXI6OnNlbGVjdChjb250YWlucygncTEyJykpICU+JSBsYXR0aWNlOjpoaXN0b2dyYW0ofnExMiwuKSAtLT4KPCEtLSBgYGAgLS0+Cgo8IS0tIGBgYHtyfSAtLT4KPCEtLSB4dGFicyhmb3JtdWxhID0gfnExMStxMTIsZGF0YSA9IGRmX2xhYnMpIC0tPgo8IS0tIGBgYCAtLT4KCgo8IS0tICMjIFdlYnNpdGUgdmlzaXRzIC0tPgoKPCEtLSBgYGB7cn0gLS0+CjwhLS0gZGZfbGFicyAlPiUgc2VsZWN0KGNvbnRhaW5zKCdxMTNyJykpICU+JSBtYXAofnV0aWxpdHlfaGlzdG9ncmFtcGxvdHRlcigueCkpIC0tPgo8IS0tIGBgYCAtLT4KPCEtLSAjIyBRMjQgLS0+Cgo8IS0tIGBgYHtyfSAtLT4KPCEtLSBkZl9sYWJzICU+JSBzZWxlY3QoY29udGFpbnMoJ3EyNHInKSkgJT4lIG1hcCh+dXRpbGl0eV9oaXN0b2dyYW1wbG90dGVyKC54KSkgLS0+CjwhLS0gZGZfbGFicyAlPiUgc2VsZWN0KGNvbnRhaW5zKCdxMjRyJykpICU+JSBtYXBfZGYofmFzLm51bWVyaWMoLngpKSAlPiUgY29yKCkgJT4lIGNvcnJwbG90Ojpjb3JycGxvdChvcmRlciA9ICdoY2x1c3QnKSAtLT4KPCEtLSBgYGAgLS0+CjwhLS0gIyMgUTI1IC0tPgoKPCEtLSBgYGB7cn0gLS0+CjwhLS0gZGZfbGFicyAlPiUgc2VsZWN0KGNvbnRhaW5zKCdxMjVyJykpICU+JSBtYXAofnV0aWxpdHlfaGlzdG9ncmFtcGxvdHRlcigueCkpIC0tPgo8IS0tIGRmX2xhYnMgJT4lIHNlbGVjdChjb250YWlucygncTI1cicpKSAlPiUgbWFwX2RmKH5hcy5udW1lcmljKC54KSkgJT4lIGNvcigpICU+JSBjb3JycGxvdDo6Y29ycnBsb3Qob3JkZXIgPSAnaGNsdXN0JykgLS0+CjwhLS0gYGBgIC0tPgoKPCEtLSAjIyBRMjYgLS0+Cgo8IS0tIGBgYHtyfSAtLT4KPCEtLSBkZl9sYWJzICU+JSBzZWxlY3QoY29udGFpbnMoJ3EyNnInKSkgJT4lIG1hcCh+dXRpbGl0eV9oaXN0b2dyYW1wbG90dGVyKC54KSkgLS0+CjwhLS0gZGZfbGFicyAlPiUgc2VsZWN0KGNvbnRhaW5zKCdxMjZyJykpICU+JSBtYXBfZGYofmFzLm51bWVyaWMoLngpKSAlPiUgY29yKCkgJT4lIGNvcnJwbG90Ojpjb3JycGxvdChvcmRlciA9ICdoY2x1c3QnKSAtLT4KPCEtLSBgYGAgLS0+Cgo8IS0tICMjIFE1IC0tPgoKPCEtLSBgYGB7cn0gLS0+CjwhLS0gZGZfbGFicyAlPiUgZHBseXI6OnNlbGVjdChjb250YWlucygncTVyMScpKSAlPiUgbGF0dGljZTo6aGlzdG9ncmFtKH5xNXIxLC4sc2NhbGVzPWxpc3QoeD1saXN0KHJvdD0zMCkpKSAtLT4KPCEtLSBgYGAgLS0+Cgo8IS0tICMjIFE0OCAtLT4KCjwhLS0gYGBge3J9IC0tPgo8IS0tIGRmX2xhYnMgJT4lIGRwbHlyOjpzZWxlY3QoY29udGFpbnMoJ3E0OCcpKSAlPiUgbGF0dGljZTo6aGlzdG9ncmFtKH5xNDgsLixzY2FsZXM9bGlzdCh4PWxpc3Qocm90PTMwKSkpIC0tPgo8IS0tIGBgYCAtLT4KCjwhLS0gIyMgUTQ5IC0tPgoKPCEtLSBgYGB7cn0gLS0+CjwhLS0gZGZfbGFicyAlPiUgZHBseXI6OnNlbGVjdChjb250YWlucygncTQ5JykpICU+JSBsYXR0aWNlOjpoaXN0b2dyYW0ofnE0OSwuLHNjYWxlcz1saXN0KHg9bGlzdChyb3Q9MzApKSkgLS0+CjwhLS0gYGBgIC0tPgoKPCEtLSAjIyBRNTAgLS0+Cgo8IS0tIGBgYHtyfSAtLT4KPCEtLSBkZl9sYWJzICU+JSBzZWxlY3QoY29udGFpbnMoJ3E1MHInKSkgJT4lIG1hcCh+dXRpbGl0eV9oaXN0b2dyYW1wbG90dGVyKC54KSkgLS0+CjwhLS0gYGBgIC0tPgoKPCEtLSAjIyBRNTYgLS0+Cgo8IS0tIGBgYHtyfSAtLT4KPCEtLSBkZl9sYWJzICU+JSBkcGx5cjo6c2VsZWN0KGNvbnRhaW5zKCdxNTYnKSkgJT4lIGxhdHRpY2U6Omhpc3RvZ3JhbSh+cTU2LC4sc2NhbGVzPWxpc3QoeD1saXN0KHJvdD0zMCkpKSAtLT4KPCEtLSBgYGAgLS0+CgoKCgojIFJlbW92ZSBtaXNzaW5nIHZhbHVlcwoKIyMgSGFuZGxlIHRoZSBjYXNlIG9mIHRoZSBtaXNzaW5nIGFwcHM/CmBgYHtyfQpkZl9udW1zJHExMltpcy5uYShkZl9udW1zJHExMildIDwtIDAKZGZfbnVtcyAlPiUgeHRhYnMofnExMitxMTEsLixhZGROQSA9IFQpCmRmX251bXMgJT4lIHh0YWJzKH5xNHIxMCtxMTEsLixhZGROQSA9IFQpCmRmX251bXMgJT4lIHh0YWJzKH5xNHIxMStxMTEsLixhZGROQSA9IFQpCiMgUlVMRSAoQSk6IElGIHE0cjExPVRSVUUsIGl0IG1lYW5zIHlvdSBoYXZlIG5vIGFwcHMuIFNvIHRoYXQgbWVhbnMgcTExIGhhcyB0byBlcXVhbCA2LCBpLmUuIE5PTkUuIERhdGEgc2hvd3MgdGhpcyBpcyB2aW9sYXRlZC4gQ29ycmVjdGluZyB1c2luZyB0aGlzIHJ1bGUuCmRmX251bXMkcTExW2RmX251bXMkcTRyMTE9PVRSVUVdIDwtIDYKZGZfbnVtcyAlPiUgeHRhYnMofnE0cjExK3ExMSwuLGFkZE5BID0gVCkKYGBgCgojIyBTbWFsbCBjaGFuZ2VzCgpTaW5jZSBxMTEgY2FuIGJlIG9yZGluYWwsICJub25lIiBzaG91bGQgZXF1YWwgMCBpbnN0ZWFkIG9mIDYgdG8gcHJlc2VydmUgb3JkaW5hbGl0eQpgYGB7cn0KIyBSVUxFIChCKTogU2V0IHExMT02IHRvIHExMT0wCmRmX251bXMkcTExW2RmX251bXMkcTExPT02XSA8LSAwCmRmX251bXMgJT4lIHh0YWJzKH5xMTEsLiwgYWRkTkEgPSBUKQpgYGAKCidEb250IGtub3cnIGRvZXNuJ3QgYWRkIHZhbHVlLiBQZXJoYXBzIHRoZXNlIGNhbiBiZSBzZXQgdG8gYE5BYCBhbmQgdGhlbiBpbXB1dGVkIHVzaW5nIGBtaWNlYC4KCmBgYHtyfQojIFJVTEUgKEMpOiBTZXQgcTExIERvbnQga25vdyB0byBOQQpkZl9udW1zJHExMVtkZl9udW1zJHExMT09MF0gPC0gTkEKZGZfbnVtcyAlPiUgeHRhYnMofnExMSwuLCBhZGROQSA9IFQpCmBgYAoKYGBge3J9CiMgUlVMRSAoRCk6IEFsbCBOQSB2YWx1ZXMgZm9yIHExMiBzZXQgdG8gNiwgc2luY2UgSSdtIGFwcHJveGltYXRpbmcgdGhhdCBpZiB5b3UgZG9uJ3QgaGF2ZSBhbnkgYXBwcywgbWlnaHQgYXMgd2VsbCBjb3VsZCBhcyBmcmVlPwpkZl9udW1zJHExMltpcy5uYShkZl9udW1zJHExMildIDwtIDYKZGZfbnVtcyAlPiUgeHRhYnMofnExMiwuLCBhZGROQSA9IFQpCmBgYAoKYGBge3J9Cm1hcF9pbnQoZGZfbnVtcyx+c3VtKGlzLm5hKC54KSkpICU+JSBzb3J0KCkgJT4lIHRhaWwoMykgJT4lIGJhcmNoYXJ0KG1haW49J01pc3NpbmcgdmFsdWVzJykKYGBgCgoKIyMgSW1wdXRpbmcgdXNpbmcgYG1pY2VgCmBgYHtyfQptYXBfZGYoZGZfbnVtcyx+YXMuZmFjdG9yKC54KSkgJT4lIAogIG1pY2U6Om1pY2UocHJpbnRGbGFnID0gVCwgbSA9IDUsIG1ldGhvZCA9ICdyZicpIC0+IG1pY2VGaXQKZGZfbnVtcyA8LSB0YmxfZGYobWljZTo6Y29tcGxldGUobWljZUZpdCkpCmBgYAoKIyBCaSBQbG90cwoKYGBge3J9CiMgcXVlc3Rpb25zX3RvX2NvbnNvbGlkYXRlIDwtIGMoJ3ExMycsJ3EyNCcsJ3EyNScsJ3EyNicpCiMgcGxvdF9iaV9wbG90cyhkZl9udW1zICU+JSBkcGx5cjo6c2VsZWN0KGNvbnRhaW5zKHF1ZXN0aW9uc190b19jb25zb2xpZGF0ZVsxXSkpLHF1ZXN0aW9uc190b19jb25zb2xpZGF0ZVsxXSkKIyBwbG90X2JpX3Bsb3RzKGRmX251bXMgJT4lIGRwbHlyOjpzZWxlY3QoY29udGFpbnMocXVlc3Rpb25zX3RvX2NvbnNvbGlkYXRlWzJdKSkscXVlc3Rpb25zX3RvX2NvbnNvbGlkYXRlWzJdLCB4bGltPWMoMCwuMDUpLCB5bGltPWMoLTAuMDEsMC4wMDIpKQojIHBsb3RfYmlfcGxvdHMoZGZfbnVtcyAlPiUgZHBseXI6OnNlbGVjdChjb250YWlucyhxdWVzdGlvbnNfdG9fY29uc29saWRhdGVbM10pKSxxdWVzdGlvbnNfdG9fY29uc29saWRhdGVbM10pCiMgcGxvdF9iaV9wbG90cyhkZl9udW1zICU+JSBkcGx5cjo6c2VsZWN0KGNvbnRhaW5zKHF1ZXN0aW9uc190b19jb25zb2xpZGF0ZVs0XSkpLHF1ZXN0aW9uc190b19jb25zb2xpZGF0ZVs0XSwgeGxpbT1jKDAsMC4wNSkseWxpbT1jKC0wLjAxMSwwLjAwNSkpCmBgYAoKIyBEYXRhIFByZXAKCiMjIFN1YiBncm91cGluZwoKYGBge3J9CmRmX251bXMgPC0gbWFwX2RmKGRmX251bXMsfmFzLm51bWVyaWMoYXMuY2hhcmFjdGVyKC54KSkpCmRmX251bXNfYWRqIDwtIGRmX251bXMgJT4lICAKICBhZGp1c3RfcTEzKCkgJT4lIAogIGFkanVzdF9xMjQoKSAlPiUgCiAgYWRqdXN0X3EyNSgpICU+JSAKICBhZGp1c3RfcTI2KCkgJT4lIAogIGFkanVzdF9xMigpICU+JSAKICBhZGp1c3RfcTQoKSAlPiUgCiAgYWRqdXN0X3JhY2UoKSAlPiUgCiAgYWRqdXN0X2dlbmRlcigpICU+JSAKICBhZGp1c3RfbWFyaXRhbCgpICU+JSAKICBhZGp1c3RfaW5jb21lKCkgJT4lCiAgYWRqdXN0X2FnZSgpICU+JSAKICBhZGp1c3RfcTExKCkgJT4lIAogIGFkanVzdF9uYW1lcygpICU+JSAKICBhZGp1c3RfY2hpbGRyZW4oKQoKZ2xpbXBzZShkZl9udW1zX2FkaikKYGBgCgojIyBTZWxlY3Rpb24gb2YgYmFzaXMgdmFyaWFibGVzCgpgYGB7cn0Kc2V0MSA8LSBjKAogICdxMV9hZ2UnLAogICMgJ3ExMV9hcHBudW0nLAogICMgJ3ExMl9mcmVlYXBwcGMnLAogICdxNDhfZWR1JywKICAncTQ5X21hcml0YWwnLAogICdxNTByMV9ub2NoaWxkJywKICAncTU2X2luY29tZScsCiAgIyAncTU3X21mJywKICAjICdxMTNfdmlzaXRmcmVxX3NvY2lhbCcsCiAgIyAncTEzX3Zpc2l0ZnJlcV9tdXNpYycsCiAgIyAncTEzX3Zpc2l0ZnJlcV92aWRlbycsCiAgJ3EyNF90ZWNoX3Bvc2F0dCcsCiAgJ3EyNF90ZWNoX2VudGVyJywKICAncTI0X3RlY2hfY29tbScsCiAgJ3EyNF90ZWNoX25lZ2F0dicsCiAgIyAncTI1X3Byc25sdHlfbGVhZGVyJywKICAjICdxMjVfcHJzbmx0eV9yaXNrJywKICAjICdxMjVfcHJzbmx0eV9kcml2ZScsCiAgIyAncTI1X3Byc25sdHlfZm9sbG93ZXInLAogICdxMjZfc2hvcHNhdnZ5X2JhcmdhaW4nLAogICdxMjZfc2hvcHNhdnZ5X2JyYW5kcycsCiAgJ3EyNl9zaG9wc2F2dnlfZWFybjJzcGVuZCcsCiAgJ3EyNl9zaG9wc2F2dnlfYXBwbG92ZXInLAogICdxMjZfc2hvcHNhdnZ5X2NoaWxkcmVuJywKICAncTJfYXBwbGUnLAogICdxMl9hbmRyaW9kJywKICAncTJfd2luZG93cycsCiAgIyAncTJfdGFibGV0JywKICAjICdxMl9vdGhlcicsCiAgIyAncTRfdXNlX211c2ljX2FwcHMnLAogICMgJ3E0X3VzZV90dl9hcHBzJywKICAjICdxNF91c2VfZ2FtZV9hcHBzJywKICAjICdxNF91c2Vfc29jaWFsX2FwcHMnLAogICMgJ3E0X3VzZV9uZXdzX2FwcHMnLAogICMgJ3E0X3VzZV9zaG9wX2FwcHMnLAogICMgJ3E0X3VzZV9ub25lX2FwcHMnLAogICdxNTRfd2hpdGUnLAogICdxNTRfYmxhY2snLAogICdxNTRfYXNpYW4nLAogICdxNTRfaGF3YWknLAogICdxNTRfbmF0aXZlJywKICAjICdxNTRfb3RoZXInLAogICdxNTVfbGF0aW5vJwopCmBgYAoKYGBge3J9CmRmX251bXNfYWRqX2JhY2t1cCA8LSBkZl9udW1zX2FkagojIGRmX251bXNfYWRqIDwtIGRmX251bXNfYWRqX2JhY2t1cApgYGAKCgpgYGB7cn0KZGZfbnVtc19hZGogPC0gZGZfbnVtc19hZGogJT4lIGRwbHlyOjpzZWxlY3Qob25lX29mKHNldDEpKQpgYGAKCgojIFNjYWxpbmcKYGBge3J9CnNjYWxpbmdfd2FudGVkIDwtIFQKbWlubWF4X3dhbnRlZCA8LSBGCmlmIChzY2FsaW5nX3dhbnRlZCkgewogIGRmX251bXNfYWRqc2NhbGVkIDwtIHNjYWxlKGRmX251bXNfYWRqKQogIGNlbnRlcnMgPC0gYXR0cmlidXRlcyhkZl9udW1zX2FkanNjYWxlZClbWzNdXQogIHNwcmVhZHMgPC0gYXR0cmlidXRlcyhkZl9udW1zX2FkanNjYWxlZClbWzRdXQogIGRmX251bXNfYWRqc2NhbGVkIDwtIHRibF9kZihkZl9udW1zX2FkanNjYWxlZCkKfQppZihtaW5tYXhfd2FudGVkKXsKICBkZl9udW1zX2FkanNjYWxlZCA8LSBtYXBfZGYoZGZfbnVtc19hZGosIH5taW5tYXgoLngpKQp9CmlmKCFzY2FsaW5nX3dhbnRlZCAmICFtaW5tYXhfd2FudGVkKXsKICBkZl9udW1zX2FkanNjYWxlZCA8LSBkZl9udW1zX2Fkagp9CmhlYWQoZGZfbnVtc19hZGpzY2FsZWQpCmBgYAoKIyBDb3JyZWxhdGlvbiBQbG90CmBgYHtyfQpkZl9udW1zX2FkanNjYWxlZCAlPiUgY29yKCkgJT4lIGNvcnJwbG90KG1ldGhvZCA9ICdzaGFkZScsdGwuY29sID0gJ2JsYWNrJyx0bC5jZXggPSAuOSwgb3JkZXIgPSAnaGNsdXN0JywgaGNsdXN0Lm1ldGhvZCA9ICd3YXJkLkQyJykKYGBgCgojIERpc3NpbWlsYXJpdHkgQ2FsY3VsYXRpb25zCgpgYGB7cn0KIyBvcmRlcmVkPWMoMTo0LDExLDEzOjI4KQojIHN5bW1fYmluPWMoNjoxMCwxMiwyOTo0NykKIyBkZl9udW1zX2FkanNjYWxlZFtvcmRlcmVkXSA8LSBtYXBfZGYoZGZfbnVtc19hZGpzY2FsZWRbb3JkZXJlZF0sfmFzLm9yZGVyZWQoLngpKQojIGRmX251bXNfYWRqc2NhbGVkW3N5bW1fYmluXSA8LSBtYXBfZGYoZGZfbnVtc19hZGpzY2FsZWRbc3ltbV9iaW5dLH5hcy5mYWN0b3IoLngpKQpkaXN0TWF0IDwtIGRhaXN5KGRmX251bXNfYWRqc2NhbGVkKQpgYGAKCgojIFNpbXBsZSBjbHVzdGVyaW5nCgojIyBIIGNsdXN0CgojIyMgSG93IGNvcGhlbmV0aWMgY2hhbmdlcyB3aXRoIGNsdXN0ZXJpbmcgbWV0aG9kPwpgYGB7cn0KbWV0aG9kcyA8LSBjKCdjb21wbGV0ZScsJ2F2ZXJhZ2UnLCd3YXJkLkQnLCd3YXJkLkQyJywnbWVkaWFuJywnbWNxdWl0dHknLCdjZW50cm9pZCcpCm1ldGhvZF92c19jb3AgPC0gbWFwX2RibChtZXRob2RzLH5jb3IoY29waGVuZXRpYyhoY2x1c3QoZCA9IGRpc3RNYXQsIG1ldGhvZCA9IC54KSksIGRpc3RNYXQpKQpuYW1lcyhtZXRob2RfdnNfY29wKSA8LSBtZXRob2RzCmJhcmNoYXJ0KHNvcnQobWV0aG9kX3ZzX2NvcCkpCmBgYAoKYGBge3J9CmsgPSA0CgpoY2x1c3RGaXQgPC0gaGNsdXN0KGQgPSBkaXN0TWF0LCBtZXRob2QgPSAnd2FyZC5EMicpCnBsb3QoaGNsdXN0Rml0LCBsYWJlbHMgPSBGKQpyZWN0LmhjbHVzdChoY2x1c3RGaXQsIGs9aywgYm9yZGVyPSJyZWQiKQpgYGAKCgpgYGB7cn0KaGNsdXN0X3NlZ21lbnRzIDwtIGN1dHJlZShoY2x1c3RGaXQsIGsgPSBrKQp0YWJsZShoY2x1c3Rfc2VnbWVudHMpCmNsdXNwbG90KGRmX251bXNfYWRqc2NhbGVkLCBoY2x1c3Rfc2VnbWVudHMsIGNvbG9yPVRSVUUsIHNoYWRlPVRSVUUsIGxhYmVscz00LCBsaW5lcz0wLCBtYWluPSJIQ2x1c3QgcGxvdCIpCmBgYAoKYGBge3J9CnNlZy5zdW1tKGRmX251bXNfYWRqLCBoY2x1c3Rfc2VnbWVudHMpIC0+IGNlbnRyb2lkcwpjZW50cm9pZHMKYGBgCgpgYGB7cn0KY3V0Rml0IDwtIGN1dHJlZShoY2x1c3RGaXQsIGspCnBsb3Qoc2lsaG91ZXR0ZShjdXRGaXQsZGlzdE1hdCkpCmBgYAoKIyMgSy1tZWFucwoKIyMjIEhvdyBtYW55IGNsdXN0ZXJzIHRvIHVzZT8KCmBgYHtyfQp3c3NwbG90IDwtIGZ1bmN0aW9uKG51bXN1YiwgbmM9MTUsIHNlZWQ9MjIyKSB7CiAgd3NzIDwtIChucm93KG51bXN1YiktMSkqc3VtKGFwcGx5KG51bXN1YiwyLHZhcikpCiAgZm9yIChpIGluIDI6bmMpIHsKICAgIHNldC5zZWVkKHNlZWQpCiAgICB3c3NbaV0gPC0gc3VtKGttZWFucyhudW1zdWIsIGNlbnRlcnM9aSwgaXRlci5tYXggPSAxZTQpJHdpdGhpbnNzKX0KICBwbG90KDE6bmMsIHdzcywgdHlwZT0iYiIsIHhsYWI9Ik51bWJlciBvZiBDbHVzdGVycyIsCiAgICAgICB5bGFiPSJXaXRoaW4gZ3JvdXBzIHN1bSBvZiBzcXVhcmVzIil9Cndzc3Bsb3QoZGZfbnVtc19hZGpzY2FsZWQpCmBgYAoKIyMjIFNvbHZpbmcgdGhlIGstbWVhbnMgbW9kZWwKCmBgYHtyfQojIFVzaW5nIGNsdXN0ZXIgY2VudGVycyBmcm9tIGhjbHVzdDoKc2VnLnN1bW0oZGZfbnVtc19hZGpzY2FsZWQsIGhjbHVzdF9zZWdtZW50cykgLT4ga21lYW5zX2NlbnRyb2lkcwpjbHVzdGVycmVzdWx0cyA8LSBrbWVhbnMoeCA9IGRmX251bXNfYWRqc2NhbGVkLCBjZW50ZXJzID0ga21lYW5zX2NlbnRyb2lkc1ssLTFdKQpyc3F1YXJlIDwtIGNsdXN0ZXJyZXN1bHRzJGJldHdlZW5zcy9jbHVzdGVycmVzdWx0cyR0b3RzcwpjYXQoJ1xuV2l0aGluIFNTOicsY2x1c3RlcnJlc3VsdHMkd2l0aGluc3MsJyBTaXplczpcbicsY2x1c3RlcnJlc3VsdHMkc2l6ZSwnXG5yc3E6JywgcnNxdWFyZSkKY2x1c3Bsb3QoZGZfbnVtc19hZGpzY2FsZWQsIGNsdXN0ZXJyZXN1bHRzJGNsdXN0ZXIsIGNvbG9yPVRSVUUsIHNoYWRlPVRSVUUsIGxhYmVscz00LCBsaW5lcz0wLCBtYWluPSJLLW1lYW5zIGNsdXN0ZXIgcGxvdCIpCgojIFVzaW5nIG51bWJlciBvZiBjbHVzdGVycyArIHJhbmRvbSBzdGFydHMKa19rbWVhbnMgPSA1CmNsdXN0ZXJyZXN1bHRzIDwtIGttZWFucyh4ID0gZGZfbnVtc19hZGpzY2FsZWQsIGNlbnRlcnMgPSBrX2ttZWFucykKcnNxdWFyZSA8LSBjbHVzdGVycmVzdWx0cyRiZXR3ZWVuc3MvY2x1c3RlcnJlc3VsdHMkdG90c3MKY2F0KCdcbldpdGhpbiBTUzonLGNsdXN0ZXJyZXN1bHRzJHdpdGhpbnNzLCcgU2l6ZXM6XG4nLGNsdXN0ZXJyZXN1bHRzJHNpemUsJ1xucnNxOicsIHJzcXVhcmUpCmNsdXNwbG90KGRmX251bXNfYWRqc2NhbGVkLCBjbHVzdGVycmVzdWx0cyRjbHVzdGVyLCBjb2xvcj1UUlVFLCBzaGFkZT1UUlVFLCBsYWJlbHM9NCwgbGluZXM9MCwgbWFpbj0iSy1tZWFucyBjbHVzdGVyIHBsb3QiKQpgYGAKCmBgYHtyfQpzZWcuc3VtbShkZl9udW1zX2FkaiwgY2x1c3RlcnJlc3VsdHMkY2x1c3RlcikgLT4gc2Vnc3VtbWFyeV9yZXN1bHRzCnNlZ3N1bW1hcnlfcmVzdWx0cwpgYGAKCiMjIFBBTQoKYGBge3J9CnBhbUZpdHMgPC0gdGliYmxlKGtfcGFtID0gMjoxMCkKcGFtRml0cyRwYW1GaXRzIDwtIG1hcChwYW1GaXRzJGtfcGFtLCB+cGFtKGRmX251bXNfYWRqc2NhbGVkLCBrID0gLngpKQpwYW1GaXRzJHNpbF9hdmdfd2lkdGggPC0gbWFwX2RibChwYW1GaXRzJHBhbUZpdHMsfi54JHNpbGluZm8kYXZnLndpZHRoKQpwYW1GaXRzCmBgYAoKYGBge3J9CnBhbUZpdHMgJT4lIAogIHh5cGxvdChzaWxfYXZnX3dpZHRofmFzLmZhY3RvcihrX3BhbSksLix0eXBlPSdiJykKYGBgCgpgYGB7cn0KcGxvdChwYW1GaXRzJHBhbUZpdHNbWzRdXSkKYGBgCgpgYGB7cn0Kc2VnLnN1bW0oZGZfbnVtc19hZGosIHBhbUZpdHMkcGFtRml0c1tbNF1dJGNsdXN0ZXJpbmcpCmBgYAoKIyBNb2RlbCBiYXNlZAoKYGBge3J9Cm1jbHVzdEZpdHMgPC0gdGliYmxlKG1jbHVzdF9jbHVzdGVycz0yOjgpCm1jbHVzdEZpdHMkbWNsdXN0Rml0cyA8LSBtYXAobWNsdXN0Rml0cyRtY2x1c3RfY2x1c3RlcnMsIH5NY2x1c3QoZGZfbnVtc19hZGpzY2FsZWQsIEcgPSAueCkpCm1jbHVzdEZpdHMkYmljIDwtIG1hcF9kYmwobWNsdXN0Rml0cyRtY2x1c3RGaXRzLCB+LnhbWydiaWMnXV0pCm1jbHVzdEZpdHMkbG9nbGlrIDwtIG1hcF9kYmwobWNsdXN0Rml0cyRtY2x1c3RGaXRzLCB+LnhbWydsb2dsaWsnXV0pCm1jbHVzdEZpdHMKYGBgCgpgYGB7cn0KbWNsdXN0Rml0cyAlPiUgCiAgeHlwbG90KGJpYytsb2dsaWt+YXMuZmFjdG9yKG1jbHVzdF9jbHVzdGVycyksLiwgYXV0by5rZXkgPSBULCB0eXBlID0gJ2InKQpgYGAKCmBgYHtyfQpzdW1tYXJ5KG1jbHVzdEZpdHNbWzIsJ21jbHVzdEZpdHMnXV0pCmBgYAoKYGBge3J9Cm1jbHVzdF9jbHVzdGVycyA8LSBtY2x1c3RGaXRzW1syLCdtY2x1c3RGaXRzJ11dJGNsYXNzaWZpY2F0aW9uCmNsdXNwbG90KGRmX251bXNfYWRqLCBtY2x1c3RfY2x1c3RlcnMsIGNvbG9yPVRSVUUsIHNoYWRlPVRSVUUsIGxhYmVscz00LCBsaW5lcz0wLCBtYWluPSJNIENsdXN0IFBsb3QsIGsgPSA0IikKYGBgCgpgYGB7cn0Kc2VnLnN1bW0oZGZfbnVtc19hZGosIG1jbHVzdF9jbHVzdGVycykKYGBgCmBgYHtyfQptY2x1c3RfZGlzdE1hdCA8LSBkYWlzeShkZl9udW1zX2FkaikKcGxvdChzaWxob3VldHRlKG1jbHVzdF9jbHVzdGVycyxtY2x1c3RfZGlzdE1hdCkpCmBgYAoKPCEtLSAjIyB0c25lIC0tPgoKPCEtLSBgYGB7cn0gLS0+CjwhLS0gdHNuZUZpdCA8LSBSdHNuZTo6UnRzbmUoWCA9IGFzLm1hdHJpeChkZl9udW1zX2FkanNjYWxlZCksIHBlcnBsZXhpdHkgPSA0MCwgbWF4X2l0ZXIgPSA1MDAwLCBwY2EgPSBGQUxTRSwgbW9tZW50dW0gPSAwLjc1KSAtLT4KPCEtLSB0c25lRml0IC0tPgo8IS0tIHRvUGxvdCA8LSB0YmxfZGYodHNuZUZpdCRZKSAtLT4KPCEtLSBuYW1lcyh0b1Bsb3QpIDwtIGMoJ1gnLCdZJykgLS0+CjwhLS0geHlwbG90KFh+WSwgZGF0YSA9IHRvUGxvdCkgLS0+CjwhLS0gYGBgIC0tPgoKPCEtLSBgYGB7cn0gLS0+CjwhLS0gZGZfbnVtc19hZGogJT4lIGJpbmRfY29scyh0b1Bsb3QpICU+JSAgLS0+CjwhLS0gICBsYXR0aWNlOjp4eXBsb3QoWX5YLGdyb3Vwcz1xMTNfdmlzaXRmcmVxX3ZpZGVvLGRhdGE9LixhdXRvLmtleT1saXN0KGNvbHVtbnM9NikpIC0tPgo8IS0tIGBgYCAtLT4KCjwhLS0gYGBge3J9IC0tPgo8IS0tIGRmX251bXNfYWRqICU+JSBiaW5kX2NvbHModG9QbG90KSAlPiUgd3JpdGVfY3N2KHBhdGggPSAnLi4vZGF0YS90c25lX291dC5jc3YnLCBjb2xfbmFtZXMgPSBUKSAtLT4KPCEtLSBgYGAgLS0+